// ----------------------------------------------------------------------------
// diabindEnumLineNumbers.h
// DIA Enumerate source files
// ----------------------------------------------------------------------------

#pragma once

#include "diabindLineNumber.h"

// ----------------------------------------------------------------------------

namespace diabind
{

// ----------------------------------------------------------------------------

interface IEnumLineNumbers
{
    virtual ~IEnumLineNumbers() {}

    virtual LONG get_Count() = 0;
    virtual CLineNumberPtr Item(DWORD index) = 0;
};
typedef boost::shared_ptr< IEnumLineNumbers > CEnumLineNumbersPtr;

// ----------------------------------------------------------------------------

template< class DiaEnumLineNumbersT >
class CEnumLineNumbersImpl : public IEnumLineNumbers
{
    typedef _com_IIID< DiaEnumLineNumbersT, &__uuidof(DiaEnumLineNumbersT) > CIiid;
    typedef _com_ptr_t< CIiid > CImplPtr;
public:
    explicit CEnumLineNumbersImpl(const CImplPtr &pEnumLineNumbers)
        : m_pEnumLineNumbers(pEnumLineNumbers)
    {
        HRESULT hResult = m_pEnumLineNumbers->get_Count(&m_nCount);
        if (S_OK != hResult)
            throw CException(hResult, "IDiaEnumLineNumbers::get_Count");
    }

    virtual LONG get_Count() override
    {
        return m_nCount;
    }

    virtual CLineNumberPtr Item(DWORD index) override
    {
        if (index >= static_cast<DWORD>(m_nCount))
            throw CPyException(PyExc_IndexError, "index out of range");

        return ItemT(&DiaEnumLineNumbersT::Item, "IDiaEnumLineNumbers::Item", index);
    }

protected:
    template< class DiaLineNumberT >
    CLineNumberPtr ItemT(
        HRESULT (STDMETHODCALLTYPE DiaEnumLineNumbersT::*pMethod)(DWORD, DiaLineNumberT **),
        const char *szMethodName,
        DWORD index
    )
    {
        _com_ptr_t< _com_IIID<DiaLineNumberT, &__uuidof(DiaLineNumberT)> > pLineNumber;
        HRESULT hResult = (m_pEnumLineNumbers->*pMethod)(index, &pLineNumber);
        if (S_OK != hResult)
            throw CException(hResult, szMethodName);

        return CLineNumberPtr( new CLineNumberImpl<DiaLineNumberT>(pLineNumber) );
    }

private:
    CImplPtr m_pEnumLineNumbers;
    LONG m_nCount;
};

// ----------------------------------------------------------------------------

}   // namespace diabind

// ----------------------------------------------------------------------------
